home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume89
/
workbnch
/
flist12.2
< prev
next >
Wrap
Text File
|
1989-03-15
|
52KB
|
1,956 lines
Path: xanth!nic.MR.NET!hal!cwjcc!mailrus!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v89i050: flist - scrollable cli and directory lister v1.2, Part02/03
Message-ID: <12229@swan.ulowell.edu>
Date: 15 Mar 89 17:22:32 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 1945
Approved: page@swan.ulowell.edu
Submitted-by: alliant!mistress!berry (Steve -Raz- Berry)
Posting-number: Volume 89, Issue 50
Archive-name: workbench/flist12.2
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# menu.c
# parse.c
# pathname.c
# readme
# rexxglue.asm
# rexxport.c
# This archive created: Wed Mar 15 12:12:37 1989
cat << \SHAR_EOF > menu.c
/**************************************************************************
* M E N U E X A M P L E P R O G R A M - JOHN DRAPER
* (originally it was anyway)
*
* Modified (mangled) by Steve Berry 7/77/88
*
***************************************************************************/
#include <libraries/arpbase.h>
#include "flist.h"
void *OpenLibrary();
struct Window *OpenWindow();
struct IntuiMessage *GetMsg();
struct Window *BuildSysRequest();
extern void Cleanup(),scrprt(),getkey();
extern struct Gadget pg;
extern struct Window *winptr;
extern struct IntuiText TRUEtext;
extern struct Window *winptr;
extern struct Screen *scrptr;
extern struct RastPort *rp;
extern struct FileLock *lock, olddir;
extern long line, numfiles, collum, first;
extern char (*fname[MAXDIR])[FCHARS];
extern char (*finfo[MAXDIR])[4];
extern char conline[256];
long top;
/***************************************************************************
M E N U D E F I N I T I O N S
***************************************************************************/
#define NUM_MENUS 3
/* Copies of this structure will get "stamped" into many more */
/* Allocated later */
struct IntuiText generic = {
0, 1, /* Bluepen, Whitepen */
JAM2, 5, /* mode, LeftEdge */
0, NL, /* Top (to be filled later), Font */
NL, /* Name (to be filled later) */
NL /* Next one */
};
/* Menu numbers */
#define PROJ_MENU 0
#define DIR_MENU 1
#define SORT_MENU 2
/* Menu Widths */
#define FIL_WIDTH 80
#define DIR_WIDTH 100
#define SORT_WIDTH 120
#define ITEM_WIDTH 150
#define REQ_WIDTH 100
int item_widths[ NUM_MENUS ] = {150,250,150};
/* All items in these menus has the following flags set */
#define BOX_FILL ITEMTEXT | ITEMENABLED | HIGHBOX
#define BLACK_FILL COMMSEQ | ITEMTEXT | ITEMENABLED | HIGHCOMP
#define HAS_CHECKS COMMSEQ | ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT
/** FILE MENU ITEMS **/
#define NUM_FILE_ITEMS 4
#define DO_ITEM 0
#define ICON_ITEM 1
#define ABOUT_ITEM 2
#define QUIT_ITEM 3
struct MenuItem file_items[NUM_FILE_ITEMS];
struct IntuiText file_names[NUM_FILE_ITEMS];
char *filemenu_names[] = {
"Execute REXX",
"Iconify",
"About",
"Quit"
};
char *filemenu_short[] = {
"E",
"I",
"B",
"Q"
};
struct Menu fmenu = {
NL, /* Pointer to next menu, fill in later */
0, 0, FIL_WIDTH, 10, /* LeftEdge, TopEdge, Width, Height */
MENUENABLED, /* FLAGS */
"Project", /* Menu name */
NL /* First item structure */
};
/************ Next menu ****************/
/** FILE MENU ITEMS **/
#define NUM_DIR_ITEMS 7
#define PARENT_ITEM 0
#define CHANGE_ITEM 1
#define ARP_ITEM 2
#define REGET_ITEM 3
#define KILL_ITEM 4
#define RENAME_ITEM 5
#define MAKEDIR_ITEM 6
struct MenuItem dir_items[NUM_DIR_ITEMS];
struct IntuiText dir_names[NUM_DIR_ITEMS];
char *dirmenu_names[] = {
" Parent Directory",
" Change Directory",
" ARP Change to Volume",
" Get Directory",
" Kill File",
" Rename File",
" Make Dir"
};
char *dirmenu_short[] = {
"P",
"D",
"A",
"G",
"K",
"R",
"N"
};
struct Menu dmenu = {
NL, /* Pointer to next menu, fill in later */
100, 0, DIR_WIDTH, 10, /* LeftEdge, TopEdge, Width, Height */
MENUENABLED, /* FLAGS */
"Directory", /* Menu name */
NL /* First item structure */
};
/************ Next menu ****************/
/** FILE MENU ITEMS **/
#define NUM_SORT_ITEMS 5
#define ALPHABET_ITEM 0
#define SIZE_ITEM 1
#define TIME_ITEM 2
#define PATTERN_ITEM 3
#define DAY_ITEM 4
struct MenuItem sort_items[NUM_SORT_ITEMS];
struct IntuiText sort_names[NUM_SORT_ITEMS];
char *sortmenu_names[] = {
"Alphabeticly",
"By Size",
"By Time",
"By Pattern",
"By Day"
};
char *sortmenu_short[] = {
"S",
"Z",
"T",
"O",
"Y"
};
struct Menu smenu = {
NL, /* Pointer to next menu, fill in later */
200, 0, SORT_WIDTH, 10, /* LeftEdge, TopEdge, Width, Height */
MENUENABLED, /* FLAGS */
"Sort List", /* Menu name */
NL /* First item structure */
};
/***************************************************************************
AUTO REQUEST INTUITEXT STRUCTURES
***************************************************************************/
struct IntuiText Auto3 = {
REDP, WHTP,
JAM1, 15,
35, NL,
"Freely Redistributable for noncomercial purposes. ", NULL
};
struct IntuiText Auto2 = {
REDP, WHTP,
JAM1, 15,
17, NL,
" Inspired by the PD Flist on IBM mainframes ", &Auto3
};
struct IntuiText AboutText = {
REDP, WHTP,
JAM1, 20,
5, NL,
" Flist was written by Steve (Raz) Berry ", &Auto2
};
/***************************************************************************
M A I N P R O G R A M M O D U L E
***************************************************************************/
long mousey, mousex;
menu()
{
ULONG class; /* Message class from Intuition */
USHORT code; /* Menu code info from Intuition */
struct MenuItem *item;
long gadown=FALSE;
struct IntuiMessage *message;
struct Gadget *igad;
register short prevy=0;
register int i,temp;
char buf[256];
mousey = 0;
mousex = 0;
fmenu.FirstItem = &file_items[0];
fmenu.NextMenu = &dmenu;
dmenu.NextMenu = &smenu;
NewMenu( &fmenu, filemenu_names, filemenu_short, file_items, file_names,
NUM_FILE_ITEMS, item_widths[0], BLACK_FILL);
dmenu.FirstItem = &dir_items[0];
NewMenu( &dmenu, dirmenu_names, dirmenu_short, dir_items, dir_names,
NUM_DIR_ITEMS, item_widths[1], HAS_CHECKS);
smenu.FirstItem = &sort_items[0];
NewMenu( &smenu, sortmenu_names, sortmenu_short, sort_items, sort_names,
NUM_SORT_ITEMS, item_widths[2], BLACK_FILL);
/* sort_items[0].MutualExclude = 0xfffe; */
top = 0; /* this is the pointer to the first file on the screen */
SetMenuStrip(winptr, &fmenu); /* Set up the menu here */
ShowTitle(scrptr,TRUE); /* Do show the screen Title. */
sort(0); /* sort the list alphabetically */
refresh();
drawcur();
for (;;)
{
if ((message = (struct IntuiMessage *)GetMsg(winptr->UserPort)) == 0L) {
Wait(1L<<winptr->UserPort->mp_SigBit);
continue;
}
class = message->Class;
code = message->Code;
igad = (struct Gadget *)message->IAddress;
mousey = message->MouseY;
mousex = message->MouseX;
switch (class) {
case RAWKEY:
getkey(message); /* message is replied to in routine */
break;
case MOUSEMOVE:
ReplyMsg(message);
if(gadown){
#ifdef KILLEXTRA
/* get rid of any extra messages */
while((message = (struct IntuiMessage *)GetMsg(winptr->UserPort)) != 0L) {
mousey = message->MouseY;
ReplyMsg(message);
if((prevy<mousey)&&(line<numfiles))
top++;
if((prevy>mousey)&&(top>0))
top--;
prevy = mousey;
}
#endif
if((prevy<mousey)&&(line<numfiles-1)){
line++;
top++;
}
if((prevy>mousey)&&(top>0)){
if (line>0)
line--;
top--;
}
prevy = mousey;
temp = numfiles-top;
scrprt(temp,top);
}
break;
case GADGETUP:
ReplyMsg(message);
drawline(collum,TRUE);
drawcur();
gadown = FALSE;
break;
case GADGETDOWN:
ReplyMsg(message);
blankcur();
switch ( i = igad->GadgetID) {
case FGAD: /* the prop gadget here... */
gadown = TRUE;
strcpy(buf,conline);
conline[first] = 0;
drawline(collum,TRUE);
strcpy(conline,buf);
drawline(collum,TRUE);
break;
}
break;
case CLOSEWINDOW:
ReplyMsg(message);
Cleanup();
exit(0);
break;
case MENUPICK:
ReplyMsg(message);
blankcur();
while (code != MENUNULL) {
#ifdef DEBUG
sprintf(buf,"Code is %ld Menunum is %ld",code, MENUNUM(code));
auto_req(buf);
#endif
domenu(MENUNUM(code), ITEMNUM(code),
SUBNUM(code));
item = ItemAddress(&fmenu, MENUNUM(code));
if (item->NextSelect == code)
break;
code = item->NextSelect;
item->NextSelect = MENUNULL;
}
drawcur();
break;
case MOUSEBUTTONS:
ReplyMsg(message);
break;
} /* Case */
} /* for */
} /* End of Main */
/***************************************************************************
C R E A T E A N E W M E N U
***************************************************************************/
NewMenu ( menu, item_names, item_short, menu_items, menu_text,
num_items, Mwidth, flag)
struct Menu *menu; /* Menu structure */
char *item_names[]; /* Pointer to array of item names */
char *item_short[]; /* Pointer to array of shortcut char */
struct MenuItem menu_items[]; /* pointer to array of structures */
struct IntuiText menu_text[]; /* Pointer to array of text structures */
int num_items; /* Number of items */
int Mwidth; /* Menu Width */
long flag; /* Special Item flag for ALL items */
{
int i;
int height = 0;
for (i=0; i< num_items; i++) {
menu_text[i] = generic; /* stamp generic template */
menu_text[i].IText = item_names[i]; /* mv string ptrs */
menu_items[i].NextItem = &menu_items[i+1]; /* Lnk to nxt item */
menu_items[i].TopEdge = 10 * i; /* Top rect of item */
menu_items[i].LeftEdge = 2;
menu_items[i].Height = 8;
menu_items[i].ItemFill = (APTR)&menu_text[i];
menu_items[i].Width = Mwidth;
menu_items[i].MutualExclude = 0;
menu_items[i].Command = item_short[i][0];
menu_items[i].Flags = (USHORT)flag;
menu_items[i].SubItem = NULL;
menu_items[i].NextSelect = MENUNULL;
height += 10;
}
menu_items[num_items-1].NextItem = NULL;
menu->Height = height;
}
/* DO THE MENU SELECTIONS */
domenu(menu, item, subitem)
int menu, item, subitem;
{
char buf[256];
int i;
switch (menu) {
case PROJ_MENU:
switch (item) {
case DO_ITEM:
dorexx();
break;
case ICON_ITEM:
tticon();
break;
case QUIT_ITEM:
if(scrptr->FirstWindow->NextWindow != NULL)
auto_req("Kill all other Applications first");
else {
Cleanup();
exit(0);
}
break;
case ABOUT_ITEM:
AutoRequest(winptr, &AboutText, &TRUEtext, &TRUEtext,
0L, 0L, 450L, 80L );
break;
}
break;
case DIR_MENU:
for (i=0;i<NUM_DIR_ITEMS;i++)
dir_items[i].Flags = HAS_CHECKS;
switch (item) {
case PARENT_ITEM:
parent();
refresh();
break;
case CHANGE_ITEM:
if (*finfo[line][0] < 0){
sprintf(buf,"%s Not a directory",fname[line]);
auto_req(buf);
}else {
changedir(fname[line]);
refresh();
}
break;
case ARP_ITEM:
if (Wbargs() == 0){
UnLock(olddir);
refresh();
}
break;
case REGET_ITEM:
getdir();
refresh();
break;
case KILL_ITEM:
kill(fname[line]);
refresh();
break;
case RENAME_ITEM:
rename_file(fname[line]);
refresh();
break;
case MAKEDIR_ITEM:
make_dir();
refresh();
break;
}
break;
case SORT_MENU:
switch (item) {
case ALPHABET_ITEM:
sort(0);
refresh();
break;
case SIZE_ITEM:
sort(1);
refresh();
break;
case TIME_ITEM:
sort(2);
refresh();
break;
case PATTERN_ITEM:
sort(3);
refresh();
break;
case DAY_ITEM:
sort(4);
refresh();
break;
}
break;
}
}
SHAR_EOF
cat << \SHAR_EOF > parse.c
/*
* parse routines for flist...
*
* uses arp functions.
*
*/
#include <libraries/arpbase.h>
#include <stdio.h>
#include "flist.h"
/* Global stuff for ARP */
char *CLI_Template = ",FROM/K";
char *CLI_Help = "Type filename(s) or FROM and a file with name of files";
/* global flist stuff */
struct AnchorPath *ap = NULL;
long (*finfo[MAXDIR])[4]; /* miscelaneous info -- file size,blocks,dir type etc... */
char (*fname[MAXDIR])[FCHARS]; /* file name and comment */
char (*comm[MAXDIR])[FCHARS];
char (*fstring[MAXDIR])[LEN_DATSTRING];
char (*ftime[MAXDIR])[LEN_DATSTRING];
struct FileLock *startdir = NULL, *lock = NULL, *olddir = NULL;
long numfiles,getcurrentdir();
long parse(argc,argv)
long argc;
char *argv[];
{
long i,rc = -99;
for (i=0;i<MAXDIR;i++) /* zero out the memory arrays */
fname[i] = 0;
ap = (struct AnchorPath *)ArpAllocMem(sizeof(struct AnchorPath),FAST);
if(ap == NULL)
return OUT_OF_MEMORY;
ap->ap_BreakBits = SIGBREAKB_CTRL_C;
ap->ap_Length = 0;
if((argv[1] != 0) && (argc > 0)){
if(!getcurrentdir(argv[1]))
return -98;
strcat(argv[1],"*");
rc = FindFirst(argv[1],ap);
if(rc == NULL)
rc = Fillarray();
}
else{
if ((argc > 1) && (argv[2] != NULL))
rc = other_input(argv[2]);
else{
if(argc == 0)
rc = Wbargs(); /* do we have Workbench? */
else{
if(!getcurrentdir(""))
return -98;
rc = FindFirst("*",ap); /* user only typed 'flist' */
if(rc == NULL) /* so we are going to give him the */
rc = Fillarray(); /* current directory */
}
}
}
return rc; /* return code should always be sent */
}
FreeFlistMem()
{
if(ap != NULL )
FreeAnchorChain(ap);
}
/* Stuff all the filenames and pertinent information into */
/* the flist arrays */
long Fillarray()
{
long rc = NULL;
struct DateTime dt;
int i;
numfiles = 0;
dt.dat_Format = FORMAT_DOS;
dt.dat_StrDay = NULL;
dt.dat_Flags = DTB_SUBST;
while(rc != ERROR_NO_MORE_ENTRIES){
if(get_array_mem(numfiles) == OUT_OF_MEMORY)
return OUT_OF_MEMORY;
strcpy(fname[numfiles],&ap->ap_Info.fib_FileName);
strcpy(comm[numfiles],&ap->ap_Info.fib_Comment);
dt.dat_Stamp = ap->ap_Info.fib_Date;
dt.dat_StrDate = fstring[numfiles];
dt.dat_StrTime = ftime[numfiles];
(*finfo[numfiles])[0] = ap->ap_Info.fib_DirEntryType;
(*finfo[numfiles])[1] = ap->ap_Info.fib_Protection;
(*finfo[numfiles])[2] = ap->ap_Info.fib_Size;
(*finfo[numfiles])[3] = ap->ap_Info.fib_NumBlocks;
if((rc = StamptoStr(&dt)) != NULL)
break;
rc = FindNext(ap);
if( ++numfiles > MAXDIR || rc != NULL)
break;
}
for (i=numfiles;i<MAXDIR;i++) /* free all array memory not being used */
if (fname[i] != 0) {
FreeMem(fname[i],FCHARS);
/* FreeMem(comm[i],FCHARS); */
FreeMem(finfo[i],16L);
FreeMem(fstring[i],LEN_DATSTRING);
FreeMem(ftime[i],LEN_DATSTRING);
fname[i] = 0;
finfo[i] = 0;
fstring[i] = 0;
ftime[i] = 0;
}
if(rc == ERROR_NO_MORE_ENTRIES)
return NULL;
return rc;
}
/* The user has not supplied any filenames or input for the File */
/* template. Here we check for the optional FROM keyword. */
long other_input(argv)
char *argv[];
{
FILE *fp;
char *buffer;
struct DateTime dt;
register long rc;
int i;
if ((buffer = (char *)ArpAllocMem(LINESIZE,FAST)) == NULL)
return OUT_OF_MEMORY;
if ((fp = fopen(argv,"r")) == NULL)
return -99L;
if (!getcurrentdir(""))
return -98L;
dt.dat_Format = FORMAT_USA;
dt.dat_StrDay = NULL;
dt.dat_Flags = DTB_SUBST;
numfiles = 0;
while (feof(fp) == NULL){
if(get_array_mem(numfiles) == OUT_OF_MEMORY)
return OUT_OF_MEMORY;
fscanf(fp,"%s",buffer);
rc = FindFirst(buffer,ap);
if (rc != NULL )
break;
strcpy(fname[numfiles],buffer);
strcpy(comm[numfiles],&ap->ap_Info.fib_Comment);
(*finfo[numfiles])[0] = ap->ap_Info.fib_DirEntryType;
(*finfo[numfiles])[1] = ap->ap_Info.fib_Protection;
(*finfo[numfiles])[2] = ap->ap_Info.fib_Size;
(*finfo[numfiles])[3] = ap->ap_Info.fib_NumBlocks;
dt.dat_Stamp = ap->ap_Info.fib_Date;
dt.dat_StrDate = fstring[numfiles];
dt.dat_StrTime = ftime[numfiles];
if((rc = StamptoStr(&dt)) != NULL)
break;
if( ++numfiles > MAXDIR | rc != NULL)
break;
}
if (feof(fp) == NULL){
if (rc == NULL)
rc = (LONG)ferror(fp);
}
else
numfiles--;
for (i=numfiles;i<MAXDIR;i++) /* free all array memory not being used */
if (fname[i] != 0) {
FreeMem(fname[i],FCHARS);
/* FreeMem(comm[i],FCHARS); */
FreeMem(finfo[i],16L);
FreeMem(fstring[i],LEN_DATSTRING);
FreeMem(ftime[i],LEN_DATSTRING);
fname[i] = 0;
finfo[i] = 0;
fstring[i] = 0;
ftime[i] = 0;
}
fclose(fp);
return rc;
}
long get_array_mem(index)
long index;
{
/* If the memory array already has a block allocated to it return to
caller... otherwise allocate one */
if (fname[index] != 0L)
return 0L;
fname[index] = (char *)AllocMem(FCHARS,FAST);
/* comm[index] = (char *)AllocMem(FCHARS,FAST); */
finfo[index] = (LONG *)AllocMem(16L,FAST);
fstring[index] = (char *)AllocMem(LEN_DATSTRING,FAST);
ftime[index] = (char *)AllocMem(LEN_DATSTRING,FAST);
if( ftime[index] == NULL | fstring[index] == NULL \
| fname[index] == NULL | /* comm[index] == NULL | */ finfo[index] == NULL )
return OUT_OF_MEMORY;
else
return 0L;
}
/*
** more Arp stuff for Workbench support
*/
BYTE dir[DSIZE], name[FCHARS];
getarp(mask,fib)
ULONG mask;
struct FileInfoBlock *fib;
{
long rc;
struct DateTime dt;
dt.dat_Format = FORMAT_USA;
dt.dat_StrDay = NULL;
dt.dat_Flags = DTB_SUBST;
strcpy(fname[numfiles],&fib->fib_FileName);
strcpy(comm[numfiles],&fib->fib_Comment);
(*finfo[numfiles])[0] = fib->fib_DirEntryType;
(*finfo[numfiles])[1] = fib->fib_Protection;
(*finfo[numfiles])[2] = fib->fib_Size;
(*finfo[numfiles])[3] = fib->fib_NumBlocks;
dt.dat_Stamp = ap->ap_Info.fib_Date;
dt.dat_StrDate = fstring[numfiles];
dt.dat_StrTime = ftime[numfiles];
if((rc = StamptoStr(&dt)) != NULL)
return rc;
numfiles++;
return 0L; /* tell Arp to put this entry in the requester */
/* ok, this is the fun part ... cheath told me that there
is a bug in the handling of the return code. this is the fix. */
#asm
move.l #0,d0 ; d0 MUST contain the return code
move.l d0,4(sp) ; 4(sp) is the part that gets munged to the
; correct value
#endasm
}
struct FileRequester arpfr = {
/* Hailing text */
(BYTE *)"Select a directory, then click on OK.",
NULL, /* string to put the final name */
NULL, /* string to put the directory entry */
NULL, /* Window for the files */
NULL, /* what calls getarp? */
NULL, /* reserved */
NULL, /* function to be called */
NULL /* reserved */
};
long Wbargs() /* use the arp file requester to get the file names */
{
long dummy;
char dname[FCHARS];
strcpy(dir,"RAM:");
strcpy(dname,"Select directory only.");
arpfr.fr_Dir = dir;
arpfr.fr_File = dname;
dummy = FileRequest(&arpfr);
if(dummy == NULL) /* user selects cancel -- so abort */
return 1;
olddir = lock; /* save this for later */
if(strcmp(dir,"") == 0)
getcurrentdir("");
else {
lock = Lock(dir,ACCESS_READ);
if(lock == NULL) {
auto_req("Can't find requested directory.");
return 1;
}
}
if (startdir == NULL)
startdir = CurrentDir(lock);
else
CurrentDir(lock);
TackOn(dir,"*");
dummy = FindFirst(dir,ap);
if(dummy == NULL)
dummy = Fillarray();
return (dummy == NULL || dummy == ERROR_NO_MORE_ENTRIES) ? 0 : 1;
}
long getcurrentdir(str)
char *str;
{
/* This is the only way I have ever been able to reliably get the
current directory */
/* Save the Value of the Directory we are in now. */
if (str[0] == '\0'){
struct Process *proc = FindTask(NULL);
lock = DupLock(proc->pr_CurrentDir);
startdir = CurrentDir(lock);
return TRUE;
} else {
lock = Lock(str);
startdir = CurrentDir(lock);
return (startdir == 0) ? FALSE : TRUE;
}
}
SHAR_EOF
cat << \SHAR_EOF > pathname.c
/** pathname.c
*
* Copyright 1988, W.G.J. Langeveld
* All Rights Reserved
* Freely Distributable
*
* Expand path name given a lock on a file name. Emulates ARP function
* of the same name, which is slightly unreliable.
*
* Mods to device name generation by Steve (Raz) Berry
* 12/31/88 (New Years Eve!)
*
**/
#include <stdio.h>
char *index();
extern void auto_req();
#define FIBSIZ ((long) sizeof(struct FileInfoBlock))
int PathName(plock, buffer)
struct FileLock *plock;
char *buffer;
{
struct FileLock *llock, *curdir;
char *temp, *pos, buf[100];
struct FileInfoBlock *filinf;
long rc;
llock = NULL;
filinf = NULL;
temp = NULL;
buffer[0] = '\0';
filinf = (struct FileInfoBlock *) AllocMem(FIBSIZ, MEMF_PUBLIC|MEMF_CLEAR);
if (filinf == NULL) goto cleanuplk;
temp = (char *) AllocMem(255L, MEMF_PUBLIC|MEMF_CLEAR);
if (temp == NULL) goto cleanuplk;
#ifdef DEBUG
if(plock == NULL)
auto_req("lock is null");
#endif
rc = Examine(plock, filinf);
if (rc == NULL) goto cleanuplk;
strcpy(buffer, filinf->fib_FileName);
llock = ParentDir(plock);
/*
* Now loop back through the parent directories until root is found.
* Meanwhile, keep track of the names.
*/
while (llock != NULL) {
if (Examine(llock, filinf) == NULL) goto cleanuplk;
strcpy(temp, buffer);
strcpy(buffer, filinf->fib_FileName);
strcat(buffer, "/");
strcat(buffer, temp);
curdir = ParentDir(llock);
UnLock(llock);
llock = curdir;
}
/*
* Now fix up the name
*/
if (pos = index(buffer, '/')) {
*pos = ':';
if (pos == buffer) {
strcpy(temp, "ram");
strcat(temp, buffer);
strcpy(buffer, temp);
}
} else
strcat(buffer, ":"); /* Append : to root names - swb */
cleanuplk:
if (filinf != NULL) FreeMem(filinf, FIBSIZ);
if (temp != NULL) FreeMem(temp, 255L);
if (llock != NULL) UnLock(llock);
return(strlen(buffer));
}
SHAR_EOF
cat << \SHAR_EOF > readme
Flist - The wonder program.
Version 1.2
Written by :
Steve (Raz) Berry
This product may be freely distributed, provided only a nominal fee is
charged, and all files are distributed together. This product may NOT be
distributed with a commercial product without prior written consent.
See the end of this file for a list of changes.
THINGS THAT YOU MUST DO BEFORE RUNNING FLIST:
Stack: Set your stack at 10K or so. You can set the stack on Icons
if they are project icons. Make sure they are! You will crash the
system if the stack is at the default of 4K.
ARP library: This release of Flist requires Version 1.1 of the
arp.library to be placed in you LIBS: directory. ARP may be discontinued
for future Flist releases.
Path: The easiest way to insure that Flist knows about your favorite
search paths is to set them in your startup-sequence before it exits.
(This trick works only under WorkBench 1.3)
Otherwise you will have to type the full pathname of each command.
One alternate fix is to install a Path-handler to search for your
commands. If you run Flist from the Workbench, you will NOT have any
default paths no matter what you do (it's not my fault... really).
Install the NULL: device in your system. See the docs in the
distributrion.
THINGS THAT YOU MUST NOT DO TO RUN FLIST:
Using the PD runback command without redirecting the input and output.
If you 'run >nil: <nil: flist' and you mount the NULL: device,
then you are safe.
If you just type 'runback flist' then there is an increased chance
that you will crash your machine. Here's how:
Nobody really wants to do this, do they?
1) runback flist from the CLI (and don't redirect the output).
2) endcli the CLI that spawned flist.
3) in Flist type 'run list' and return.
4) Hit the left mouse button to continue.
The reasons are many and varied as to why, lets just say that the output
of the 'run list' was sent to a nonexistant CLI.
I suggest that if you want your CLI back, you do:
'run <nil: >nil: flist'
Use only the 1.3 run command and make sure that the NULL device is
mounted.
HINT: If you use a shell, you can make an alias like so:
alias fb = "run <nil: >nil: flist []"
The NULL device handler is included in the distribution. Read the docs
for information on how to install it.
DESCRIPTION and FEATURES:
Flist is a Scrollable, configurable, interactive CLI and LIST combined.
ANY command that can be executed in a CLI can be run from Flist.
Flist will work in either the Workbench or the CLI environments.
You can iconify Flist to get it out of the way (thanks Leo!) and save
the price of a 2 bitplane hires screen.
Changing directory, changing to a parent directory, Deleting files or
directories, using the ARP filerequestor (to change directory) are
builtin functions.
Hitting the Escape key will insert the file name (on the current line)
into the input area (to the right of the filename).
The input area scrolls to the left and right as needed, and allows up to
90 characters per line.
Directory entries of up to 999 files are supported.
Flist opens windows for execution so it's under the mouse.
Sort the list of files alphabetically, by size, by time or by
the supplied pattern.
If you use snipit, type 'snipit x +3 y +5' to snip from Flist.
Need help remembering the keystrokes? Hit the Help key, that's what its
there for. You'll get a summary of all of the control sequences that are
currently available.
Yes there is an AREXX port. It doesn't do too many things at the moment,
and you must initiate the conversation, but it's a start. Suggestions
on further implementations are welcome.
FURTHER CONSIDERATIONS:
Read the Docs. I mean it. I don't want people sending me e-mail bombs
that read like :
"I was using your dumb Flist program when it decided to
delete my file when I hit control-k. I though you would get a file
requestor or somthing!"
Remember, this is only a README.
KNOWN BUGS:
Sorting by time will sort using the hour of creation only.
If you slide the screen down and open a window on the Workbench screen,
leaving both screens visible, the window will open on the Flist screen
instead of the Workbench.
*** This is more interesting than a bug, (in other words I can't fix it)
but if you spawn a 'loadwb' (Load Workbench) from Flist, or even when
Flist is the frontmost screen, the Amiga workbench takes over the screen
permanent like, and uses it for its own. Flist remains running but
can't be terminated.
Fifteen color Pointer animations change the workbench screen colors to
those matching Flist.
Not so configurable in this release. Sorry.
Still haven't allowed for any screen size other than 640x200.
I know this is stupid but this utility is for me, and this is what I
use. If someone is persistant enough and sends me the code for figuring
out the current screen size...
RELEASE HISTORY:
V1.0 Initial release. (Only jdow saw this)
V1.1 Bug fixes to the Arexx port. No major changes from V1.0
V1.2 Major new release. Lots of changes and additions.
1. It's harder to hang flist from the REXX port
(I haven't been able to do it yet)
2. New REXX Commands:
makedir - make a new directory
changedir - change to a directory eg:
'changedir flist'
rename - rename a file using string requestor.
redraw - redraw the screen.
request - bring up the ARP requestor.
3. Menu support (and shortcuts) for all keystrokes.
(as well as an attempt at extended selection support)
4. New commands added:
makedir
execute rexx macro (via string requestor)
rename file
sort by pattern
sort by date.
sort by day.
5. Bug fixes to cursor movment routines, as well as adding
cntrl-U (erase line). Also insert mode is now the only
mode of entry.
6. Supports SHIFT-UP and SHIFT-DOWN cursor keys to move
10 lines up or down the list. Also SHIFT left, right
to move to the begining or the end of the line respectively.
7. Uses default screen colors.
8. Internal changes to static memory allocation for
efficiency. In other words, it uses less memory.
9. Fixed misterious bug causing the original CLI to
generate a Software Error. All better now.
swb 1/23/89
Flist is a BeerWare product of 'The Checkered Ball'
SHAR_EOF
cat << \SHAR_EOF > rexxglue.asm
* === rexxglue.asm =====================================================
*
* Copyright (c) 1986, 1987 by William S. Hawes (All Rights Reserved)
*
* ======================================================================
* "Glue" routines for calling functions in the ARexx Systems Library.
* All calls assume that the external _RexxSysBase has been set to the
* ARexx SYstems library base by a call to OpenLibrary.
INCLUDE "rexx/storage.i"
INCLUDE "rexx/rxslib.i"
XREF _RexxSysBase
* First calling convention:
* 1, 2, or 3 parameters in (A0,A1,D0), return value in D0.
; node = AddClipNode(&header,&name,value,length)
XDEF _AddClipNode
_AddClipNode:
move.w #_LVOAddClipNode,d1
bra CallSeq1
; node = AddRsrcNode(&header,&name,size)
XDEF _AddRsrcNode
_AddRsrcNode:
move.w #_LVOAddRsrcNode,d1
bra CallSeq1
; count = CloseF(filehandle)
XDEF _CloseF
_CloseF
move.w #_LVOCloseF,d1
bra.s CallSeq1
; test = CmpString(&string1,&string2)
XDEF _CmpString
_CmpString:
move.w #_LVOCmpString,d1
bra.s CallSeq1
; envptr = CurrentEnv(rxtptr)
XDEF _CurrentEnv
_CurrentEnv:
moveq #_LVOCurrentEnv,d1
bra.s CallSeq1
; error = CVc2x(&buffer,&string,length)
XDEF _CVc2x
_CVc2x:
move.w #_LVOCVc2x,d1
bra.s CallSeq1
; error = CVx2c(&buffer,&string,length)
XDEF _CVx2c
_CVx2c:
move.w #_LVOCVx2c,d1
bra.s CallSeq1
; ClosePublicPort(&header,&name)
XDEF _ClosePublicPort
_ClosePublicPort:
move.w #_LVOClosePublicPort,d1
bra.s CallSeq1
; spptr = CreateDOSPkt()
XDEF _CreateDOSPkt
_CreateDOSPkt:
move.w #_LVOCreateDOSPkt,d1
bra.s CallSeq1
; msgptr = CreateRexxMsg(&replyport,&fileext,&hostname)
XDEF _CreateRexxMsg
_CreateRexxMsg:
move.w #_LVOCreateRexxMsg,d1
bra.s CallSeq1
; DeleteArgstring(argptr)
XDEF _DeleteArgstring
_DeleteArgstring:
move.w #_LVODeleteArgstring,d1
bra.s CallSeq1
; DeleteRexxMsg(msgptr)
XDEF _DeleteRexxMsg
_DeleteRexxMsg:
move.w #_LVODeleteRexxMsg,d1
bra.s CallSeq1
; code = DOSCommand(&string,filehandle)
XDEF _DOSCommand
_DOSCommand:
move.w #_LVODOSCommand,d1
bra.s CallSeq1
; count = DOSRead(filehandle,&buffer,length)
XDEF _DOSRead
_DOSRead:
move.w #_LVODOSRead,d1
bra.s CallSeq1
; count = DOSWrite(filehandle,&buffer,length)
XDEF _DOSWrite
_DOSWrite:
move.w #_LVODOSWrite,d1
bra.s CallSeq1
; DeleteDOSPkt(&stdpkt)
XDEF _DeleteDOSPkt
_DeleteDOSPkt:
move.w #_LVODeleteDOSPkt,d1
bra.s CallSeq1
; count = ExistF(filehandle,&buffer,length)
XDEF _ExistF
_ExistF:
move.w #_LVOExistF,d1
bra.s CallSeq1
; devptr = FindDevice(&name)
XDEF _FindDevice
_FindDevice:
move.w #_LVOFindDevice,d1
bra.s CallSeq1
; FreeSpace(envptr,memptr,length)
XDEF _FreeSpace
_FreeSpace:
moveq #_LVOFreeSpace,d1
bra.s CallSeq1
; FreePort(&msgport)
XDEF _FreePort
_FreePort:
move.w #_LVOFreePort,d1
bra.s CallSeq1
; type = IsSymbol(&string)
XDEF _IsSymbol
_IsSymbol:
moveq #_LVOIsSymbol,d1
bra.s CallSeq1
; InitList(&header)
XDEF _InitList
_InitList:
move.w #_LVOInitList,d1
bra.s CallSeq1
; signal = InitPort(&replyport)
XDEF _InitPort
_InitPort:
move.w #_LVOInitPort,d1
bra.s CallSeq1
; boolean = IsRexxMsg(msgptr)
XDEF _IsRexxMsg
_IsRexxMsg:
move.w #_LVOIsRexxMsg,d1
bra.s CallSeq1
; length = LengthArgstring(argptr)
XDEF _LengthArgstring
_LengthArgstring:
move.w #_LVOLengthArgstring,d1
; Load three arguments into (A0,A1,D0)
CallSeq1 movea.l 4(sp),a0
movea.l 8(sp),a1
move.l 12(sp),d0
; Call the library function
CallFunc move.l a6,-(sp)
movea.l _RexxSysBase,a6
jsr 0(a6,d1.w)
movea.l (sp)+,a6
rts
; argptr = ListNames(&header)
XDEF _ListNames
_ListNames:
move.w #_LVOListNames,d1
bra.s CallSeq1
; iobptr = OpenF(filehandle,&buffer,length)
XDEF _OpenF
_OpenF:
move.w #_LVOOpenF,d1
bra.s CallSeq1
; nodeptr = OpenPublicPort(&header,&name)
XDEF _OpenPublicPort
_OpenPublicPort:
move.w #_LVOOpenPublicPort,d1
bra.s CallSeq1
; count = QueueF(filehandle,&buffer,length)
XDEF _QueueF
_QueueF:
move.w #_LVOQueueF,d1
bra.s CallSeq1
; count = ReadF(filehandle,&buffer,length)
XDEF _ReadF
_ReadF:
move.w #_LVOReadF,d1
bra.s CallSeq1
; count = ReadStr(filehandle,&buffer,length)
XDEF _ReadStr
_ReadStr:
move.w #_LVOReadStr,d1
bra.s CallSeq1
; RemRsrcList(&header)
XDEF _RemRsrcList
_RemRsrcList:
move.w #_LVORemRsrcList,d1
bra.s CallSeq1
; RemRsrcNode(&header,&node)
XDEF _RemRsrcNode
_RemRsrcNode:
move.w #_LVORemRsrcNode,d1
bra.s CallSeq1
; RemClipNode(&header,&node)
XDEF _RemClipNode
_RemClipNode:
move.w #_LVORemClipNode,d1
bra.s CallSeq1
; test = StrcmpN(&string1,&string2)
XDEF _StrcmpN
_StrcmpN:
move.w #_LVOStrcmpN,d1
bra.s CallSeq1
; test = StrcmpU(&string1,&string2)
XDEF _StrcmpU
_StrcmpU:
move.w #_LVOStrcmpU,d1
bra.s CallSeq1
; test = StrcpyA(&string1,&string2)
XDEF _StrcpyA
_StrcpyA:
move.w #_LVOStrcpyA,d1
bra.s CallSeq1
; test = StrcpyN(&string1,&string2)
XDEF _StrcpyN
_StrcpyN:
move.w #_LVOStrcpyN,d1
bra.s CallSeq1
; test = StrcpyU(&string1,&string2)
XDEF _StrcpyU
_StrcpyU:
move.w #_LVOStrcpyU,d1
bra.s CallSeq1
; length = Strlen(&string)
XDEF _Strlen
_Strlen:
move.w #_LVOStrlen,d1
bra.s CallSeq1
; count = SeekF(filehandle,&buffer,length)
XDEF _SeekF
_SeekF:
move.w #_LVOSeekF,d1
bra.s CallSeq1
; count = StackF(filehandle,&buffer,length)
XDEF _StackF
_StackF:
move.w #_LVOStackF,d1
bra CallSeq1
; count = WriteF(filehandle,&buffer,length)
XDEF _WriteF
_WriteF:
move.w #_LVOWriteF,d1
bra CallSeq1
* Second calling convention: 2 parameters in (A0,D0), return value in D0.
; argptr = CreateArgstring(&string,length)
XDEF _CreateArgstring
_CreateArgstring:
moveq #_LVOCreateArgstring,d1
bra.s CallSeq2
; ClearMem(address,length)
XDEF _ClearMem
_ClearMem:
move.w #_LVOClearMem,d1
bra.s CallSeq2
; count = ClearRexxMsg(msgptr,count)
XDEF _ClearRexxMsg
_ClearRexxMsg:
move.w #_LVOClearRexxMsg,a1
bra.s CallSeq2
; nodeptr = FindRsrcNode(&header,type)
XDEF _FindRsrcNode
_FindRsrcNode:
move.w #_LVOFindRsrcNode,d1
bra.s CallSeq2
; block = GetSpace(envptr,size)
XDEF _GetSpace
_GetSpace:
moveq #_LVOGetSpace,d1
bra.s CallSeq2
; test = StrFlipN(&string1,length)
XDEF _StrflipN
_StrflipN:
move.w #_LVOStrflipN,d1
; Load two arguments (A0,D0)
CallSeq2 movea.l 4(sp),a0
move.l 8(sp),d0
bra CallFunc
* Third calling convention: 1 parameter in D0, return value in D0.
; argptr = CVi2arg(value)
XDEF _CVi2arg
_CVi2arg:
move.w #_LVOCVi2arg,d1
bra.s CallSeq3
; LockRexxBase(resource)
XDEF _LockRexxBase
_LockRexxBase:
move.w #_LVOLockRexxBase,d1
bra.s CallSeq3
; char = ToUpper(char)
XDEF _ToUpper
_ToUpper:
move.w #_LVOToUpper,d1
bra.s CallSeq3
; UnlockRexxBase(resource)
XDEF _UnlockRexxBase
_UnlockRexxBase:
move.w #_LVOUnlockRexxBase,d1
; Load one argument in D0
CallSeq3 move.l 4(sp),d0
bra CallFunc
* Fourth calling sequence: 3 parameters in (A0,D0,D1), return value in D0.
; value = CVi2a(&buffer,value,length)
XDEF _CVi2a
_CVi2a:
move.w #_LVOCVi2a,a1
bra.s CallSeq4
; boolean = FillRexxMsg(msgptr,count,mask)
XDEF _FillRexxMsg
_FillRexxMsg:
move.w #_LVOFillRexxMsg,a1
CallSeq4 movea.l 4(sp),a0
move.l 8(sp),d0
move.l 12(sp),d1
; Call the library function
move.l a6,-(sp)
movea.l _RexxSysBase,a6
jsr 0(a6,a1.w)
movea.l (sp)+,a6
rts
* Special calling sequences for multiple returns.
; value = CVa2i(&string,&digits)
XDEF _CVa2i
_CVa2i:
movea.l 4(sp),a0 ; scan pointer
move.w #_LVOCVa2i,d1
bsr CallFunc ; D0=converted value
movea.l 8(sp),a1 ; return pointer
move.l d1,(a1) ; digits scanned
rts
; boolean = ErrorMsg(code,&ssptr)
XDEF _ErrorMsg
_ErrorMsg:
move.l 4(sp),d0
moveq #_LVOErrorMsg,d1
bsr CallFunc ; D0=boolean A0=string structure
movea.l 8(sp),a1 ; return pointer
move.l a0,(a1) ; string structure
rts
END
SHAR_EOF
cat << \SHAR_EOF > rexxport.c
/*
This module is responsible for communicating with Rexx.
Specifically it opens a message port and tells rexx to execute
a program. Rexx should signal host of errors or death.
*/
#include <rexx/storage.h>
#include <rexx/rxslib.h>
#include <rexx/errors.h>
#include "flist.h"
/* system types */
extern void ClearMem(),AddPort(),FreePort(),InitPort(),RemPort(),Forbid();
extern void Permit();
extern LONG OpenLibrary();
extern struct RexxMsg *GetMsg();
extern struct RexxMsg myrexxport;
extern struct Library *RexxSysBase;
extern void control_keys();
/* My stuff */
struct FileHandle *fh;
struct RexxMsg *rxmsg;
extern char strbuf[256];
extern long collum, row, line, first, top;
#define PUBFAST MEMF_FAST+MEMF_PUBLIC+MEMF_CLEAR
void OpenRexxPort(string,port)
char *string;
struct MsgPort *port;
{
ClearMem(port,(LONG)sizeof(struct MsgPort));
InitPort(port,string);
AddPort(port);
}
void DeleteRexxPort(port)
struct MsgPort *port;
{
if(port != NULL){
RemPort(port);
FreePort(port);
}
}
struct RexxMsg *PollRexxPort(port)
struct MsgPort *port;
{
struct RexxMsg *rxport;
rxport = GetMsg(port);
return(rxport);
}
struct RexxMsg *WaitRexxPort(port)
struct MsgPort *port;
{
WaitPort(port);
return(PollRexxPort(port));
}
void CleanupRexx()
{
/* Close(fh); */
DeleteArgstring(rxmsg->rm_Args[0]);
DeleteRexxMsg(rxmsg);
}
long StartRexxProg(rexport)
struct MsgPort *rexport;
{
struct MsgPort *port;
struct Window *strptr;
strbuf[0] = '\0';
strptr = make_gadget("Enter the REXX macro name ");
if (strptr == NULL) {
auto_req("Couldn't open Requestor!");
return FALSE;
}
wait_for_event(strptr);
if (strbuf[0] == '\0') {
return FALSE;
}
rxmsg = CreateRexxMsg(rexport,"flex","flport");
rxmsg->rm_Args[0] = strbuf;
rxmsg->rm_Action = RXCOMM;
/* rxmsg->rm_Stdout = Output(); */
if(!FillRexxMsg(rxmsg, 1L, 0L)) {
DeleteRexxMsg(rxmsg);
return FALSE;
}
Forbid();
port = (struct RexxMsg *)FindPort("REXX");
if(port == NULL){
Permit();
auto_req("REXX is not here!");
CleanupRexx();
return FALSE;
}
PutMsg(port,rxmsg); /* email in it's truest form */
Permit();
return TRUE;
}
char *rexx_strings[] = {
"end",
"iconify",
"sort s",
"sort z",
"sort t",
"sort o",
"parent",
"redraw",
"reget",
"request",
"makedir",
"changedir",
"sort y"
};
dorexx()
{
struct RexxMsg *resultmsg;
char buf[256];
int equal, i;
if(RexxSysBase == NULL){
auto_req(" Rexx library not Available");
return;
}
if(!StartRexxProg(&myrexxport)){ /* start up fl.flex as a rexx task */
if (strbuf[0] != '\0')
auto_req(" PANIC - couldn't start up rexx program!");
return;
}
/* this is a communication test ... */
for(;;) {
resultmsg = WaitRexxPort(&myrexxport);
#ifdef DEBUG
sprintf(buf,"Return of -%d- , -%s-",resultmsg->rm_Result1,resultmsg->rm_Args[0]);
auto_req(buf);
#endif
if (resultmsg->rm_Result1 > 0) {
if (Strcmp(strbuf, resultmsg->rm_Args[0]) == 0) {
sprintf(buf,"Error %d in -%s.flex-.",
resultmsg->rm_Result1,strbuf);
auto_req(buf);
resultmsg->rm_Result1 = 5;
resultmsg->rm_Result2 = 0;
CleanupRexx();
return;
}
}
resultmsg->rm_Result1 = 0; /* no error */
resultmsg->rm_Result2 = 0; /* no secondary */
for(i=0;i<13;i++){
equal = Strncmp(resultmsg->rm_Args[0],rexx_strings[i],
strlen(rexx_strings[i]));
if (equal == 0)
break;
}
#ifdef DEBUG
sprintf(buf,"I = %d, string is %s",i,rexx_strings[i]);
auto_req(buf);
#endif
blankcur();
switch (i) {
case 0:
ReplyMsg(resultmsg); /* send back 'end' message */
WaitRexxPort(&myrexxport); /* wait for original Msg to ret */
CleanupRexx();
return;
case 1: /* Iconify */
tticon();
break;
case 2: /* sort by name */
sort(0);
refresh();
break;
case 3: /* sort by size */
sort(1);
refresh();
break;
case 4: /* sort by time */
sort(2);
refresh();
break;
case 5: /* sort by pattern */
sort(3);
refresh();
break;
case 6: /* get parent dir */
parent();
refresh();
break;
case 7: /* redraw screen */
control_keys(0x0c);
break;
case 8: /* reget directory */
getdir();
refresh();
break;
case 9:
control_keys(0x01); /* ARP requestor */
break;
case 10:
control_keys(0x0e); /* Makedir */
break;
case 11: /* changedir 'string' */
if (strlen(resultmsg->rm_Args[0]) > 10) {
#ifdef DEBUG
auto_req(&resultmsg->rm_Args[0][10]);
#endif
strcpy(buf,&resultmsg->rm_Args[0][10]);
changedir(buf);
refresh();
} else
auto_req("Bad arguments to CHANGEDIR.");
break;
case 12: /* sort by day */
sort(4);
refresh();
break;
default:
resultmsg->rm_Result1 = 5; /* shows an error code */
resultmsg->rm_Result2 = 0; /* no secondary */
if (Strcmp(strbuf, resultmsg->rm_Args[0]) == 0) {
sprintf(buf,"End keyword not found in -%s.flex-.",
strbuf);
auto_req(buf);
ReplyMsg(resultmsg);
WaitRexxPort(&myrexxport);
CleanupRexx();
return;
}
sprintf(buf,"Bad command -%s- from macro %s.flex",
resultmsg->rm_Args[0],strbuf);
auto_req(buf);
break;
}
ReplyMsg(resultmsg);
drawcur();
} /* end of forever */
}
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.